package rbb.itm5.bwinf.roboter.Model;

import java.awt.Point;
import java.util.ArrayList;

public abstract class RoboterInterface {
	/**Position des Roboters*/
	protected int x,y;
	/**In dieser Arraylist werden alle Position bzw. Richtungsänderungen gespeichert.*/
	protected ArrayList<Step> steps=new ArrayList<Step>();
	/**Richtungskonstanten*/
	public static final int DIRECTION_UP=0,DIRECTION_RIGHT=1,DIRECTION_DOWN=2,DIRECTION_LEFT=3,FORWARD=1,BACKWARD=-1;
	/**Merker ob Ziel gefunden wurde.*/
	protected boolean goolHasFound=false;
	/**Array zum Konvertieren der Richtungskonstante zu Name*/
	public static final String[] DIRECTION={"DIRECTION_UP","DIRECTION_RIGHT","DIRECTION_DOWN","DIRECTION_LEFT"}; 
	private int direction=DIRECTION_RIGHT;
	
	/**
	 * Gibt die aktuelle Position des Roboter in ein Point-Objekt zurück
	 * @return {@link Point} Position des Roboters.
	 * */
	public Point getPostion() {
		return new Point(x, y);
	}
	
	/**
	 * Gibt die aktuelle Blickrichtung des Roboters zurück.
	 * @return Richtung des Roboters.
	 * */
	public int getDirection() {
		return direction;
	}
	/**
	 * Gibt die relative Blickrichtung links vom Roboter zurück.
	 * @return Richtung des Roboters.
	 * */
	public int getDirectionLeft() {
		int d=direction-1;
		if(d<DIRECTION_UP) d=DIRECTION_LEFT;
		return d;
	}
	/**
	 * Gibt die relative Blickrichtung rechts vom Roboter zurück.
	 * @return Richtung des Roboters.
	 * */
	public int getDirectionRight() {
		int d=direction+1;
		if(d>DIRECTION_LEFT) d=DIRECTION_UP;
		return d;
	}
	public int getDirectionBack() {
		switch (direction) {
		case DIRECTION_UP:
			return DIRECTION_DOWN;
		case DIRECTION_RIGHT:
			return DIRECTION_LEFT;
		case DIRECTION_DOWN:
			return DIRECTION_UP;
		case DIRECTION_LEFT:
			return DIRECTION_RIGHT;
		default:
			return direction;
		}
	}
	/**Dreht den Roboter nach Links.*/
	public void turnLeft() {
		direction--;
		if(direction<DIRECTION_UP) direction=DIRECTION_LEFT;
	}
	
	/**Dreht den Roboter nach Rechts.*/
	public void turnRight() {
		direction++;
		if(direction>DIRECTION_LEFT) direction=DIRECTION_UP;
	}
	/**Setzt alle Position und Richtungen auf die Anfangswerte.
	 * Außerdem werden alle gegangen Schritte gelöscht*/
	protected void resetValues(){
		x=0;
		y=0;
		direction=DIRECTION_RIGHT;
		goolHasFound=false;
		steps.clear();
	}
	
	/**Gibt die Anzahl der durchgeführten Steuerungsanweisungen zurück.
	 * @return Anzahl der Schritte*/
	public int getStepCount() {
		return steps.size();
	}
	/**
	 * Aktuelle Position wird in das Schritt-Array gesichert
	 * */
	protected void rememberStep() {
		rememberStep(false);
	}
	/**
	 * Aktuelle Position wird in das Schritt-Array gesichert
	 * @param isRotation Wurde die Blickrichtung geändert.
	 * */
	protected void rememberStep(boolean isRotation) {
		steps.add(new Step(x, y, getDirection(),isRotation));
	}
        /**
         * Diese Methode gibt den letzten gemachten Schritt zurück.
         * @return Letzter Schritt
         */
	public Step getLastStep() {
		if(!steps.isEmpty()){
			return steps.get(steps.size()-1);
		}
		return null;
	}
        
        /**
         * Diese Methode gibt die vorige Position des Roboters
         * @return Letzte Position
         */
	public Point getLastPosition() {
		if(!steps.isEmpty()){
			Step s=steps.get(steps.size()-1);
			return new Point(s.getX(), s.getY());
		}
		return null;
	}
	
        /**
         * Diese Methode setzt die Aktuelle Blickrichtung.
         * @param direction Blickrichtung
         */
	protected void setDirection(int direction) {
		this.direction = direction;
	}
	
        /**
         * Diese Methode bewegt den Roboter um einen Schritt in die aktuelle Blickrichtung
         * @return ist vorwärts gegangen?
         * @throws Exception Pause
         */
	public abstract boolean goForward() throws Exception;
	public abstract boolean moveForward();
	/**
	 * 
	 * Diese Methode prüft ob der Roboter vor einer Wand bzw. einem Hindernis steht.
	 * @param step Anzahl der Schritte in der die Kollision geprüft wird.
	 * @param direction Richtung in der die Kollision geprüft wird.
	 * */
	protected abstract boolean hasColision(int step,int direction);
        /**
         * Diese Methode macht den letzten Schritt rückgängig.
         */
        public abstract void goBack();
        /**
         * Diese Methode prüft ob der Ausgang gefunden wurde.
         * @return Ausgang gefunden?
         */
	public abstract boolean checkGoalHasFound();
}
